<!DOCTYPE html>
<html>

<head>
    <title>vectortile test</title>
    <!-- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/axios@0.19.0/dist/axios.min.js"></script> -->
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/dat.gui@0.7.6/build/dat.gui.min.js"></script>
    <link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/maptalks/dist/maptalks.css">
    <script type="text/javascript" src="./js/maptalks.js"></script>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/three@0.109.0/build/three.min.js"></script>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/maptalks.three/dist/maptalks.three.js"></script>
    <!-- <script type="text/javascript" src="./../dist/maptalks.three.js"></script> -->
    <script type="text/javascript"
        src="https://cdn.jsdelivr.net/npm/three@0.109.0/examples/js/libs/stats.min.js"></script>
    <style>
        html,
        body {
            margin: 0px;
            height: 100%;
            width: 100%;
        }

        #map {
            width: 100%;
            height: 100%;
            /* background-color: #000; */
        }
    </style>
</head>

<body>
    <div id="map"></div>
    <script>

        var baseLaer = new maptalks.TileLayer('tile', {
            urlTemplate: 'https://mt2.google.cn/maps/vt?lyrs=m&hl=zh-CN&gl=CN&x={x}&y={y}&z={z}',
            subdomains: ['a', 'b', 'c', 'd'],
            // attribution: '&copy; <a href="http://osm.org">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/">CARTO</a>'
        });
        var map = new maptalks.Map("map", {
            "center": [-122.50826912411787, 37.85734070553329], "zoom": 14, "pitch": 40.800000000000004, "bearing": -1.8000000000000682,
            // pitch: 60,
            // bearing: 180,

            centerCross: true,
            doubleClickZoom: false,
            baseLayer: baseLaer,
            zoomControl: {
                'position': 'bottom-left'
            }
        });

        // the ThreeLayer to draw buildings
        var threeLayer = new maptalks.ThreeLayer('t', {
            forceRenderOnMoving: true,
            forceRenderOnRotating: true
            // animation: true
        });


        var vectortilelayer;
        threeLayer.prepareToDraw = function (gl, scene, camera) {
            stats = new Stats();
            stats.domElement.style.zIndex = 100;
            document.getElementById('map').appendChild(stats.domElement);

            var light = new THREE.DirectionalLight(0xffffff);
            light.position.set(0, -10, 10).normalize();
            scene.add(light);

            const url = `https://mt2.google.cn/maps/vt?lyrs=s&hl=zh-CN&gl=CN&x={x}&y={y}&z={z}`;
            vectortilelayer = threeLayer.toTerrainVectorTileLayer(url,
                {
                    // minZoom: 6,
                    // maxZoom: 16,
                    // debug: true,
                    interactive: false,
                    worker: true,
                    subdomains: ['a', 'b', 'c', 'd'],
                    scale: 1.08
                    // tileSize: [512, 512]
                }, material);

            //自定义数据访问方法
            let MAPBOX_RGB_URL = 'http://localhost:8080/tilelayer?z={z}&x={x}&y={y}', debug = true
            if (window.location.host.includes('maptalks')) {
                debug = false;
                MAPBOX_RGB_URL = 'https://{s}.tiles.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}.pngraw?access_token=pk.eyJ1IjoiemhlbmZ1IiwiYSI6ImNpb284bzNoYzAwM3h1Ym02aHlrand6OTAifQ.sKX-XKJMmgtk_oI5oIUV_g';
            }
            vectortilelayer.getTileData = function (q) {
                const { key, url, callback, img, rgbImage } = q;
                const { x, y, z } = this._getXYZOfIndex(key);
                const terrainRGBUrl = MAPBOX_RGB_URL.replace('{z}', z).replace('{x}', x).replace('{y}', y).replace('{s}', getdomain());
                rgbImage.src = terrainRGBUrl;
                rgbImage.onload = function () {
                    if (debug) {
                        setTimeout(() => {
                            const base64 = getRGBData(rgbImage);
                            callback(key, base64, img);
                        }, 3000 * Math.random());
                    } else {
                        const base64 = getRGBData(rgbImage);
                        callback(key, base64, img);
                    }

                }
                rgbImage.onerror = function () {
                    callback(key, null, img);
                }
                rgbImage.crossOrigin = 'Anonymous';
                // setTimeout(() => {
                //     callback(key, terrainRGBUrl, img);
                // }, 2000 * Math.random());
            }
            map.addLayer(vectortilelayer);
            animation();
            initGui();
        };
        threeLayer.addTo(map);


        var idx = 0;
        function getdomain() {
            const domains = ['a', 'b', 'c', 'd'];
            const s = domains[idx];
            idx++;
            if (idx > domains.length - 1) {
                idx = 0;
            }
            return s;
        }

        const canvas = document.createElement('canvas'), tileSize = 256;
        function getRGBData(image, width = tileSize, height = tileSize) {
            canvas.width = width;
            canvas.height = height;
            const ctx = canvas.getContext('2d');
            ctx.drawImage(image, 0, 0, width, height);
            return canvas.toDataURL();
        }

        const material = new THREE.MeshPhongMaterial({ transparent: true, wireframe: false });

        function animation() {
            // layer animation support Skipping frames
            if ((!map.isMoving()) && (!map.isZooming()) && (!map.isRotating()) && (!params.rotate)) {
                threeLayer._needsUpdate = !threeLayer._needsUpdate;
                if (threeLayer._needsUpdate) {
                    threeLayer._renderer.clearCanvas();
                    threeLayer.renderScene();
                }
            }
            stats.update();
            requestAnimationFrame(animation);
            if (params.rotate) {
                map.setBearing(map.getBearing() + 0.3);
            }
        }


        var params = {
            add: true,
            buildingColor: material.color.getStyle(),
            buildingOpacity: 1,
            wireframe: material.wireframe,
            animateShow: animateShow,
            show: true,
            altitude: 0,
            rotate: false,
            interactive: false
        };

        function initGui() {

            var gui = new dat.GUI();
            gui.add(params, 'add').onChange(function () {
                if (params.add) {
                    map.addLayer(vectortilelayer);
                } else {
                    map.removeLayer(vectortilelayer);
                }
            });
            gui.addColor(params, 'buildingColor').name('color').onChange(function () {
                const meshs = vectortilelayer.getBaseObjects();
                material.color.set(params.buildingColor);
                meshs.forEach(function (mesh) {
                    mesh.getObject3d().material.color.set(params.buildingColor);
                });
            });


            gui.add(params, 'buildingOpacity', 0, 1).name('opacity').onChange(function () {
                const meshs = vectortilelayer.getBaseObjects();
                material.opacity = params.buildingOpacity;
                meshs.forEach(function (mesh) {
                    mesh.getObject3d().material.opacity = params.buildingOpacity;
                });
            });
            gui.add(params, 'wireframe').onChange(function () {
                const meshs = vectortilelayer.getBaseObjects();
                material.wireframe = params.wireframe;
                meshs.forEach(function (mesh) {
                    mesh.getObject3d().material.wireframe = params.wireframe;
                });
            });

            gui.add(params, 'show').onChange(function () {
                if (params.show) {
                    vectortilelayer.show();
                } else {
                    vectortilelayer.hide();
                }
            });
            // gui.add(params, 'altitude', 0, 300).onChange(function () {
            //     const meshs = vectortilelayer.getBaseObjects();
            //     meshs.forEach(function (mesh) {
            //         mesh.setAltitude(params.altitude);
            //     });
            // });
            // gui.add(params, 'animateShow');
            gui.add(params, 'rotate');
            // gui.add(params, 'interactive').onChange(function () {
            //     vectortilelayer._opts.interactive = params.interactive;
            //     const meshs = vectortilelayer.getBaseObjects();
            //     meshs.forEach(function (mesh) {
            //         mesh.options.interactive = params.interactive;
            //     });
            // });
        }

        function animateShow() {
            const meshs = vectortilelayer.getBaseObjects();
            meshs.forEach(function (mesh) {
                mesh.animateShow({
                    duration: 1300
                });
            });
        }


    </script>
</body>

</html>
